package org.fjsei.yewu.service;

import lombok.extern.slf4j.Slf4j;
import md.specialEqp.inspect.IspPi;
import md.specialEqp.inspect.IspRepository;
import md.system.SequenceRepository;
import org.fjsei.yewu.aop.MetricsLogger;
import org.fjsei.yewu.jpa.PageOffsetFirst;
import org.fjsei.yewu.repository.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.UUID;

import static org.springframework.transaction.annotation.Propagation.REQUIRES_NEW;

/*
 * @program: spring-boot-example
 * @description:
 * @author:
 * @create: 2018-05-02 11:13
 */
//@Transactional(value="transactionManager",readOnly=true)

/**
 *可以直接编写class JpaService 没有必要再多弄个implements JpaService的接口，也是可行的。
 * */
@Slf4j
@Service
//@Qualifier("entityManagerFactoryBar")
//@Transactional(readOnly=true) 非必须的函数就不搞事务
//@Transactional(propagation = MANDATORY)  作用于所有接口函数
public class JpaServiceImpl implements JpaService {
    //@Resource  CatRepository catRepository;
    @Autowired
    private TeacherRepository teacherDao;
    @Autowired
    SequenceRepository sequenceRepository;
    @Autowired
    AuthorRepository userRepository;
    @Autowired private StoreSyncRepository storeSyncRepository;
    @Autowired
    private IspRepository iSPRepository;

    @PersistenceContext(unitName = "entityManagerFactorySei")
    private EntityManager emSei;


    @Override
    public List<Teacher> getAllTeacher() {
        List<Teacher> topics = new ArrayList<>();
        //findAll()默认是@Transactional(readOnly = true)
        teacherDao.findAll().forEach(topics::add);
        return topics;
    }

    //授权后：测试等批处理，任务入口。
   // @Transactional(value= "transactionManager",readOnly = true, transactionManager = "transactionManager")
    public Teacher getTeacher(String name) {
        Teacher teacher=new Teacher("hua","22",(byte)3);
        return teacher;
    }

    //@Transactional
    public void setTeacherAge(UUID id, String age) {
        Teacher teacher =teacherDao.getById(id);
        teacher.setAge(age);
        teacherDao.save(teacher);
    }

    @Override
    public Teacher getTeacherById(Long id) {
        //两种写法效果一样：
        Teacher teacher=emSei.getReference(Teacher.class, id);
        //Teacher teacher=teacherDao.getById(id);
        return teacher;
    }
    //@Transactional(propagation = REQUIRES_NEW, label={"noRetry"}, timeout=10)
    //@Transactional(propagation = REQUIRES_NEW,  timeout=20)
    @Transactional(propagation = REQUIRES_NEW)
    public Teacher  addTeacher(Teacher topic) {
        Long sequence =sequenceRepository.nextSeqNo("sequence_repno");
        Assert.isTrue(sequence<=9999999,"超出序列repno");
        String nostr = String.format("报告Mx#%07d", sequence);
        topic.setSno(sequence);
        topic.setRepno(nostr);
        Teacher teacher = teacherDao.save(topic);
        //Long onen=topic.getSno();
        //emSei.flush();
        //int sequence3 =sequenceRepository.setSeqStart("sequence_repno",2900+300L);
        return teacher;   //不是进来的topic
    }

    public static String getRandomString(int length){
        //定义一个字符串（A-Z，a-z，0-9）即62位；
        String str="zxcvbnmlkjhgfdsaqwertyuiopQWERTYUIOPASDFGHJKLZXCVBNM1234567890";
        //由Random生成随机数
        Random random=new Random();
        StringBuffer sb=new StringBuffer();
        //长度为几就循环几次
        for(int i=0; i<length; ++i){
            //产生0-61的数字
            int number=random.nextInt(62);
            //将产生的数字通过length次承载到sb中
            sb.append(str.charAt(number));
        }
        //将承载的字符转换成字符串
        return sb.toString();
    }

    /*
    public class BiTableMainService extends BaseMainService<BiTableMain>
        @Autowired
        private BiTableMainRepo repo;
        @PostConstruct
        public void initDao() {
            super.setRepo(repo);
        }
    * */

    /**
     * 没加Transactional：报错PSQLException: ERROR: cannot execute UPSERT in a read-only transaction
    * */
    @MetricsLogger
    @Transactional( label={"noRetry"} )
    public void upsert(){
        log.info("Upserting 1 record");
        Author user = Author.builder().id(UUID.randomUUID()).name("Rogue").city("Arkham").build();
        userRepository.upsert(user);
    }
    //@Transactional(propagation = REQUIRES_NEW, label={"noRetry"}, timeout=10)
    //@Transactional(propagation = REQUIRES_NEW,  timeout=20)  小强数据库例子是用REQUIRES_NEW

    @MetricsLogger
    @Transactional( label={"noRetry"}, timeout=60000 )
    public void upsertAll(int numberOfRecords){
        log.info("Upserting {} records", numberOfRecords);
        List<StoreSync> batch=new ArrayList<>();
         //Author user = Author.builder().id(UUID.randomUUID()).name("Rogue").city("Arkham").build();
        StoreSync ado=new StoreSync();
        ado.setId(UUID.randomUUID());
        ado.setCod("1234565");
        ado.setOid("胜多负少的");
        batch.add(ado);
        StoreSync ado2=new StoreSync();
        ado2.setId(UUID.randomUUID());
        ado2.setCod("1899500");
        ado2.setOid("xvcxc负少的4");
        batch.add(ado2);
        storeSyncRepository.upsertAll(batch);
    }
    @MetricsLogger
    @Transactional(readOnly = true)
    public void testIt(){
        Pageable pageable= PageOffsetFirst.of(3,14);
        //分片任务，保证可以重复执行，确保findAll读取出来的记录有顺序。
        log.info("testIt:测试作业{}", pageable);
        Slice<IspPi>  ispSlice= iSPRepository.readAllBy(pageable, IspPi.class);     //第一次跑只能读取简单类型字段的？后面又可以啊
        List<IspPi> isps = new ArrayList<>();
        isps= ispSlice.toList();
       // String some= isps.get(2).getIspu().getArea();
       // some= isps.get(2).getIspu().getIndCod();
        int size=isps.size();
    }
}


/* 这个是Inner join;  正常该用Left outer或=Left JOIN
SELECT c.id AS id,  c.no AS no, d.id AS bus_id9_22_0_, c.bsType AS bsType FROM Isp c ,Detail d  WHERE c.bus_id = d.id
【神奇意外#Repository】   https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections
*/